package com.edu.exam.entity.examination.online;

import com.edu.exam.enums.examination.ExamSessionState;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * 考试会话实体类
 * [所属模块] E-03 上机考试组织模块
 * 对应数据库表：exam_session
 *
 * <p>考试会话实体用于管理上机考试的完整生命周期，支持会话的创建、配置、激活、监控、
 * 暂停、终止等状态管理。通过状态机模式管理会话状态的转换，确保会话状态的一致性和可追溯性。</p>
 *
 * <p>核心功能：
 * - 会话生命周期管理：支持从创建到终止的完整生命周期管理
 * - 状态转换控制：基于状态机的状态转换控制，确保状态转换的合法性
 * - 会话配置管理：支持考试时间、安全策略、资源配置等会话配置
 * - 安全监控：集成安全监控机制，检测异常行为和风险
 * - 统计信息收集：自动收集会话过程中的各类统计信息</p>
 *
 * @author System
 * @version 1.0.0
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class ExamSession {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 会话ID
     *
     * <p>考试会话的唯一标识符，采用UUID格式生成。
     * 用于会话的唯一标识和状态管理。</p>
     */
    @Column(name = "session_id", nullable = false, length = 32, unique = true)
    private String sessionId;

    /**
     * 考试计划ID
     *
     * <p>关联的考试计划ID，标识会话所属的考试计划。
     * 用于关联考试计划信息和考试安排。</p>
     */
    @Column(name = "exam_plan_id", nullable = false, length = 32)
    private String examPlanId;

    /**
     * 考场ID
     *
     * <p>关联的考场ID，标识会话使用的考场。
     * 用于关联考场配置和安全策略。</p>
     */
    @Column(name = "exam_room_id", nullable = false, length = 32)
    private String examRoomId;

    /**
     * 会话名称
     *
     * <p>考试会话的显示名称，用于识别和展示。
     * 通常包含考试科目、时间、班级等信息。</p>
     */
    @Column(name = "session_name", nullable = false, length = 200)
    private String sessionName;

    /**
     * 会话状态
     *
     * <p>考试会话的当前状态。
     * 支持的状态：CREATED（已创建）、PENDING_AUTH（待认证）、AUTHENTICATING（认证中）、
     * AUTHENTICATED（已认证）、READY（就绪）、IN_PROGRESS（进行中）、PAUSED（暂停）、
     * SUSPENDED（挂起）、COMPLETED（已完成）、ABNORMAL（异常）、TERMINATED（终止）、EXPIRED（过期）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "session_state", nullable = false, length = 20)
    private ExamSessionState sessionState = ExamSessionState.CREATED;

    /**
     * 考试开始时间
     *
     * <p>计划开始考试的时间。
     * 用于控制考试的开始时间和自动激活机制。</p>
     */
    @Column(name = "start_time")
    private LocalDateTime startTime;

    /**
     * 考试结束时间
     *
     * <p>计划结束考试的时间。
     * 用于控制考试的结束时间和自动提交机制。</p>
     */
    @Column(name = "end_time")
    private LocalDateTime endTime;

    /**
     * 实际开始时间
     *
     * <p>考试实际开始的时间。
     * 由系统在考试正式开始时自动记录。</p>
     */
    @Column(name = "actual_start_time")
    private LocalDateTime actualStartTime;

    /**
     * 实际结束时间
     *
     * <p>考试实际结束的时间。
     * 由系统在考试结束时自动记录。</p>
     */
    @Column(name = "actual_end_time")
    private LocalDateTime actualEndTime;

    /**
     * 考试时长（分钟）
     *
     * <p>考试的总时长，单位为分钟。
     * 用于计算考试时间和自动提交。</p>
     */
    @Column(name = "duration_minutes")
    private Integer durationMinutes;

    /**
     * 延时时间（分钟）
     *
     * <p>允许的延时时间，单位为分钟。
     * 用于特殊情况下的考试延时。</p>
     */
    @Column(name = "extension_minutes")
    private Integer extensionMinutes = 0;

    /**
     * 参考人数
     *
     * <p>计划参考的学生人数。
     * 用于考试安排和资源准备。</p>
     */
    @Column(name = "expected_student_count")
    private Integer expectedStudentCount;

    /**
     * 实际参考人数
     *
     * <p>实际参加考试的学生人数。
     * 由系统根据登录和答题情况自动统计。</p>
     */
    @Column(name = "actual_student_count")
    private Integer actualStudentCount = 0;

    /**
     * 缺考人数
     *
     * <p>缺考的学生人数。
     * 由系统根据登录情况自动统计。</p>
     */
    @Column(name = "absent_student_count")
    private Integer absentStudentCount = 0;

    /**
     * 会话配置
     *
     * <p>JSON格式的会话配置信息。
     * 包含考试参数、安全策略、功能开关等配置。</p>
     */
    @Column(name = "session_config", columnDefinition = "TEXT")
    private String sessionConfig;

    /**
     * 安全策略
     *
     * <p>JSON格式的安全策略配置。
     * 包含身份认证、防作弊、监控等安全策略。</p>
     */
    @Column(name = "security_policy", columnDefinition = "TEXT")
    private String securityPolicy;

    /**
     * 会话描述
     *
     * <p>考试会话的描述信息。
     * 可选字段，用于提供会话的详细说明。</p>
     */
    @Column(name = "session_description", length = 500)
    private String sessionDescription;

    /**
     * 创建者ID
     *
     * <p>创建会话的用户ID，关联系统用户表。
     * 用于记录会话的创建者和权限控制。</p>
     */
    @Column(name = "created_by", nullable = false, length = 32)
    private String createdBy;

    /**
     * 创建者姓名
     *
     * <p>创建会话的用户姓名，用于显示和记录。
     * 冗余存储用户姓名，避免频繁关联查询用户表。</p>
     */
    @Column(name = "created_by_name", nullable = false, length = 100)
    private String createdByName;

    /**
     * 监考教师ID
     *
     * <p>主监考教师ID，关联系统用户表。
     * 用于记录监考教师和权限分配。</p>
     */
    @Column(name = "invigilator_id", length = 32)
    private String invigilatorId;

    /**
     * 监考教师姓名
     *
     * <p>主监考教师姓名，用于显示和记录。
     * 冗余存储教师姓名，避免频繁关联查询用户表。</p>
     */
    @Column(name = "invigilator_name", length = 100)
    private String invigilatorName;

    /**
     * 副监考教师ID列表
     *
     * <p>副监考教师ID列表，JSON格式。
     * 支持多个副监考教师的配置。</p>
     */
    @Column(name = "assistant_invigilators", columnDefinition = "TEXT")
    private String assistantInvigilators;

    /**
     * 是否允许延时
     *
     * <p>标识是否允许考试延时。
     * true表示允许延时，false表示不允许延时。</p>
     */
    @Column(name = "allow_extension", nullable = false)
    private Boolean allowExtension = false;

    /**
     * 最大延时时间（分钟）
     *
     * <p>允许的最大延时时间，单位为分钟。
     * 当allowExtension为true时生效。</p>
     */
    @Column(name = "max_extension_minutes")
    private Integer maxExtensionMinutes;

    /**
     * 是否自动提交
     *
     * <p>标识考试时间到后是否自动提交。
     * true表示自动提交，false表示需要手动提交。</p>
     */
    @Column(name = "auto_submit", nullable = false)
    private Boolean autoSubmit = true;

    /**
     * 自动提交缓冲时间（秒）
     *
     * <p>考试结束前的自动提交缓冲时间，单位为秒。
     * 在考试结束前指定时间内自动执行提交操作。</p>
     */
    @Column(name = "auto_submit_buffer_seconds")
    private Integer autoSubmitBufferSeconds = 30;

    /**
     * 是否允许提前交卷
     *
     * <p>标识是否允许学生提前交卷。
     * true表示允许提前交卷，false表示不允许提前交卷。</p>
     */
    @Column(name = "allow_early_submit", nullable = false)
    private Boolean allowEarlySubmit = true;

    /**
     * 提前交卷最小时间（分钟）
     *
     * <p>允许提前交卷的最小考试时间，单位为分钟。
     * 考试开始后必须经过的最短时间才允许提前交卷。</p>
     */
    @Column(name = "early_submit_min_minutes")
    private Integer earlySubmitMinMinutes = 30;

    /**
     * 异常信息
     *
     * <p>会话过程中发生的异常信息。
     * 记录会话的错误和异常情况，用于问题诊断。</p>
     */
    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;

    /**
     * 异常代码
     *
     * <p>异常的错误代码。
     * 用于错误分类和快速识别异常类型。</p>
     */
    @Column(name = "error_code", length = 50)
    private String errorCode;

    /**
     * 异常发生时间
     *
     * <p>异常发生的具体时间。
     * 用于异常时间跟踪和分析。</p>
     */
    @Column(name = "error_time")
    private LocalDateTime errorTime;

    /**
     * 会话标记
     *
     * <p>JSON格式的会话标记信息。
     * 用于记录会话的特殊状态和标记。</p>
     */
    @Column(name = "session_flags", columnDefinition = "TEXT")
    private String sessionFlags;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;

    /**
     * 更新时间
     */
    @LastModifiedDate
    @Column(name = "updated_time", nullable = false)
    private LocalDateTime updatedTime;


}